#include <iostream>

#include <cstring>

#include <unistd.h>
#include <stdlib.h>
#include <inttypes.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <sys/time.h>

// #ifndef NATIVE_SOCKET
// #include <etherfabric/ef_vi.h>
// #include <etherfabric/vi.h>
// #include <etherfabric/pd.h>
// #include <etherfabric/memreg.h>
// #include <etherfabric/pio.h>
// #include <etherfabric/checksum.h>
// #include <etherfabric/capabilities.h>
// #endif

#include "tcp_endpoint.h"
#include "net_context.h"

using namespace usnet;

const char*     LOCAL_ADDR      { "10.1.1.7" };
const char*     REMOTE_ADDR     { "10.1.1.8" };
const uint16_t  LOCAL_PORT      { 6789 };
const uint16_t  REMOTE_PORT     { 6789 };
const char*     IFNAME          { "p2p1" };

int main(int argc, char* argv[])
{
    if (NetContext::Init() == false) {
        std::cerr << "failed to init usnet context" << std::endl;
        return -1;
    }
    std::cout << "NetContext initialized" << std::endl;
    struct sockaddr_in laddr;
    if (inet_pton(AF_INET, LOCAL_ADDR, &laddr.sin_addr) != 1) {
        std::cerr << "failed to convert address: " << LOCAL_ADDR << std::endl;
        return -1;
    }
    laddr.sin_port = htons(LOCAL_PORT);
    TCPEndpoint lep { laddr };
    int connfd { -1 };
    while (true) {
        connfd = lep.Accept();
        if (connfd >= 0) {
            std::cout << "TCP connection accepted: fd = " << connfd << std::endl;
            break;
        }
        usleep(100000);
    }

    char buf[1 << 20];
    int recv_len { 0 };
    int send_len { 0 };
    struct timeval tick;
    struct timeval tock;
    while (true) {
        memset(buf, 0, sizeof(buf));
        while ((recv_len = lep.Recv(connfd, buf, sizeof(buf)) == 0));
        while ((send_len = lep.Send(connfd, buf, recv_len) == 0));
        printf("Mesg Received: %s.\n", buf);
    }

    return 0;
}